﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.Net;

namespace ExamSharedClasses {
    
    /// <summary>
    /// (k) Diese Klasse vereint gemeinsame Methoden und Variablen, die bei einer
    /// Netzwerkverbindung bei Client und Server gleichermaßen benutzt werden müssen.
    /// Der Thread wird nicht automatisch gestartet, damit das Objekt
    /// auf "unthreaded" benutzt werden kann
    /// </summary>
    public abstract class Connection {
        // Ini Datei einlesen
        public static IniFile iniFile = new IniFile(Environment.CurrentDirectory + "\\config.ini");
        private static String iniFileValue;
        // Server
        public static readonly string EXAM_SERVER_REMOTE_IP = (iniFileValue = iniFile.IniReadValue("Server", "ip")).Length > 0 ? iniFileValue : "127.0.0.1";
        public static readonly int EXAM_SERVER_REMOTE_PORT = (iniFileValue = iniFile.IniReadValue("Server", "port")).Length > 0 ? Convert.ToInt32(iniFileValue) : 7777;
        // Server - Datenbank
        public static readonly string DATABASE_SERVER_IP = (iniFileValue = iniFile.IniReadValue("Database", "ip")).Length > 0 ? iniFileValue : "127.0.0.1";
        public static readonly string DATABASE_SERVER_IP_ALTERNATIVE = "192.168.0.100";
        public static readonly string DATABASE_USER = (iniFileValue = iniFile.IniReadValue("Database", "user")).Length > 0 ? iniFileValue : "root";
        public static readonly string DATABASE_PASSWORD = (iniFileValue = iniFile.IniReadValue("Database", "password")) != null ? iniFileValue : "";
        public static readonly string DATABASE_DATABASE = (iniFileValue = iniFile.IniReadValue("Database", "name")).Length > 0 ? iniFileValue : "exam_administration";
        // Client
        public static readonly string EXAM_SERVER_IP = (iniFileValue = iniFile.IniReadValue("Client", "ip")).Length > 0 ? iniFileValue : "127.0.0.1";
        public static readonly int EXAM_SERVER_PORT = (iniFileValue = iniFile.IniReadValue("Server", "port")).Length > 0 ? Convert.ToInt32(iniFileValue) : 7777;

        public TcpListener Listener { get; set; }
        public TcpClient Client { get; set; }
        public NetworkStream Stream { get; set; }
        public BinaryFormatter Formatter { get; set; }
        public Thread ConnectionThread { get; set; }

        public virtual void ConnectionThreadMethod(){
            ;   
        }

        public Session Session { get; set; }
        public bool IsConnected { get; set; }
        public bool IsLoggedIn { get; set; }

        public Connection() {
            this.Formatter = new BinaryFormatter();
            this.Session = new Session();
            this.ConnectionThread = new Thread( ConnectionThreadMethod );     
        }
        
        public virtual void Connect() {
            Client = new TcpClient( EXAM_SERVER_IP, EXAM_SERVER_PORT );
            Stream = Client.GetStream();
        }
        public virtual void Listen() {
            ( Listener = new TcpListener( IPAddress.Parse( Connection.EXAM_SERVER_REMOTE_IP ),
                                                           Connection.EXAM_SERVER_REMOTE_PORT ) ).Start();
        }

        public virtual void Send(object o ) {
            Formatter.Serialize( Stream, o );   
        }
        public virtual object Receive() {
            return Formatter.Deserialize( Stream ) ;
        }

        public virtual void Start() {
            ConnectionThread.Start();
        }
        public virtual void Stop() {
            if ( ConnectionThread != null )
                ConnectionThread.Abort();
        }

        public virtual void Close() {
            // beim schlie0en den Thread beenden...
            Stop();

            // und alle gehaltenen referenzen nullen
            if ( Client != null )
                Client.Close();
            Client = null;
            Stream = null;
            Formatter = null;
        }
    }
}
